/**
 * Initializes validation for container.
 * 
 * @param container container. If left undefined document.body will be used
 */
function initializeValidation(container) {
  var delegators = new Array();
  var c = $(container || document.body);
  var validators = fi.internetix.validation.FieldValidatorVault.getValidators();
  for ( var i = 0, l = validators.length; i < l; i++) {
    var fields = c.select('.' + validators[i].getClassName());
    for ( var j = 0, le = fields.length; j < le; j++) {
      var field = fields[j];
      var delegator = fi.internetix.validation.ValidationDelegatorVault.getDelegator(field);
      if (!delegator) {
        delegator = new fi.internetix.validation.ValidationDelegator(field);
        fi.internetix.validation.ValidationDelegatorVault.setDelegator(field, delegator);
      }

      delegator.addValidator(validators[i]);
      delegators.push(delegator);
    }
  }
  ;

  var uniqueDelegators = delegators.uniq();
  for ( var i = 0, l = uniqueDelegators.length; i < l; i++)
    uniqueDelegators[i].validate(true);

  delete delegators;
  delete uniqueDelegators;
};

/**
 * Initializes validation for single element
 * 
 * @param element element
 */
function initializeElementValidation(element) {
  var delegator = fi.internetix.validation.ValidationDelegatorVault.getDelegator(element);
  if (!delegator) {
    delegator = new fi.internetix.validation.ValidationDelegator(element);
    fi.internetix.validation.ValidationDelegatorVault.setDelegator(element, delegator);
  }

  var validators = fi.internetix.validation.FieldValidatorVault.getValidators();
  for ( var i = 0, l = validators.length; i < l; i++) {
    var validator = validators[i];
    if (element.hasClassName(validator.getClassName()))
      delegator.addValidator(validator);
  }

  delegator.validate(true);
};

/**
 * Deinitializes validation in container
 * 
 * @param container container. If left undefined document.body will be used
 */
function deinitializeValidation(container) {
  var c = container || document.body;
  for ( var i = 0, l = c.childNodes.length; i < l; i++) {
    if (c.childNodes[i].nodeType == 1) {
      deinitializeValidation(c.childNodes[i]);
      fi.internetix.validation.ValidationDelegatorVault.releaseDelegator(c.childNodes[i]);
    }
  }
  ;
}

/**
 * Revalidates all elements
 * 
 * @param requiredCheckAsUnknown whether required should be interpret as unknown
 */
function revalidateAll(requiredCheckAsUnknown) {
  var delegators = fi.internetix.validation.ValidationDelegatorVault.getDelegators();
  for ( var i = 0, l = delegators.length; i < l; i++) {
    delegators[i].validate(requiredCheckAsUnknown);
  }
};

/**
 * Force revalidates all elements
 * 
 * @param requiredCheckAsUnknown whether required should be interpret as unknown
 */
function forceRevalidateAll(requiredCheckAsUnknown) {
  var delegators = fi.internetix.validation.ValidationDelegatorVault.getDelegators();
  for ( var i = 0, l = delegators.length; i < l; i++) {
    delegators[i].forceValidate(requiredCheckAsUnknown);
  }
};

Element.addMethods({
  validate : function(element, requiredCheckAsUnknown, forceRevalidate) {
    var delegator = fi.internetix.validation.ValidationDelegatorVault.getDelegator(element);
    if (delegator) {
      if (!forceRevalidate)
        delegator.validate(requiredCheckAsUnknown);
      else
        delegator.forceValidate(requiredCheckAsUnknown);
    }
  }
});